/**
 * 将数组转化成树结构
 */
export const arrayToTree = function <T>(arr: T[], {
  idName = "Id",
  parentIdName = "ParentId",
  childrenName = "children",
  parentNodeName = "parentNode",
  /**
   * 是否记录在node中记录父级node
   */
  isParentNode = false
} = {}): T[] {
  let map: any = {}; //构建map
  arr.forEach((i: any) => {
    map[i[idName]] = i; //构建以Id为键 当前数据为值
  });
  let treeData: any[] = [];
  arr.forEach((child: any) => {
    const mapItem = map[child[parentIdName]]; //判断当前数据的ParentId是否存在map中
    if (mapItem) {
      //存在则表示当前数据不是最顶层的数据
      //注意： 这里的map中的数据是引用了arr的它的指向还是arr,当mapItem改变时arr也会改变，踩坑点
      (mapItem[childrenName] || (mapItem[childrenName] = [])).push(child); //这里判断mapItem中是否存在child
      if (isParentNode) {
        child[parentNodeName] = mapItem;
      }
    } else {
      //不存在则是顶层数据
      treeData.push(child);
    }
  });
  return treeData;
}

/**
 * 将树结构 转化为 数组
 */
export const treeToArray = function <T>(treeList: T[], {
  childrenName = "children",
} = {}): T[] {
  let list: any[] = [];

  (function fun(childrenTreeList: any[]) {
    for (let item of childrenTreeList) {
      list.push(item);
      if (item[childrenName] && item[childrenName].length > 0) {
        fun(item[childrenName]);
      }
    }
  })(treeList)

  return list;
}

/**
 * 文件大小转换
 */
export function renderSize(filesize: number) {
  if (!filesize) {
    return "0 Bytes";
  }
  var unitArr = new Array("Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
  var index = 0;
  var srcsize = parseFloat(filesize + "");
  index = Math.floor(Math.log(srcsize) / Math.log(1024));
  var size = srcsize / Math.pow(1024, index);
  size = parseFloat(size.toFixed(2));//保留的小数位数
  return size + " " + unitArr[index];
}

/**
 * 文件下载
 */
export const downloadFile = function (url: string, fileName?: string) {
  let link = document.createElement("a");
  if ('download' in link) {
    link.setAttribute("download", fileName || "");
    link.href = url;
    link.click();
    setTimeout(() => {
      link.remove()
    }, 300)
  } else {
    window.open(url, "_blank")
  }
}

/*
 *	位数不足用0补足
 *   例子:  pad(100,4) = 0100
 */
export const pad = function (num: string | number, n: number) {
  var len = num.toString().length;
  while (len < n) {
    num = "0" + num;
    len++;
  }
  return num;
}

/**
 * 将毫秒值 转为 00:00:00 格式
 */
export function hmzToValue(value:number): string {
  let m = parseInt(`${value / 1000}`);
  let f = parseInt(`${m / 60}`);
  let s = parseInt(`${f / 60}`);
  //需要更改为毫秒值的
  return `${pad(s, 2)}:${pad(f % 60, 2)}:${pad(m % 60, 2)}`;
}

/**
 * =================
 * 创建常量功能
 */
interface ConstVarItem<K> {
  code: K,
  name: string,
}

/**
* 我们用来生成常量数据的
* 可以同时生成  数组版
* 以及code 的对象版
*/
export class ConstVar<K, T = any> {
  //用来保存初始的数据的
  public obj: Map<string, ConstVarItem<K> & T>;
  //用来保存数组形态的
  public array: (ConstVarItem<K> & T)[];
  //用来保存以code为key值的对象
  public codeObj: Map<K, ConstVarItem<K> & T>;

  constructor(obj: {
    [key: string]: ConstVarItem<K> & T
  }) {
    this.obj = new Map();
    this.codeObj = new Map();
    this.array = [];
    for (let x in obj) {
      let item = obj[x]
      this.obj.set(x, item);
      this.array.push(obj[x]);
      this.codeObj.set(item.code, obj[x])
    }
  }

  /**
   * 根据自定义的key获取数据
   */
  get(key: string): (ConstVarItem<K> & T) | {
    [key: string]: any
  } {
    return this.obj.get(key) || {}
  }

  /**
  * 根据自定义的key获取code值
  */
  getCode(key: string): K | '' {
    let item = this.obj.get(key);
    return item ? item.code : ''
  }

  /**
  * 根据自定义的key获取name值
  */
  getName(key: string): string {
    let item = this.obj.get(key);
    return item ? item.name : ''
  }

  /**
   * 根据code 获取数据
   */
  codeGet(code: any): (ConstVarItem<K> & T) | {
    [key: string]: any
  } {
    return this.codeObj.get(code) || {}
  }

  /**
   * 根据code 获取数据name
   */
  codeGetName(code: any): string {
    let item = this.codeObj.get(code);
    return item ? item.name : ''
  }
}



/**
 * =================
 * 用于基本数据信息
 */
export class BaseData {
  /**
   * id
   */
  Id: number = 0;

  /**
   *  当前系统版本号
   */
  // UnionGuid: string = uuidv1();

  /**
   * 本地临时版本号
   */
  UnionGuidTemp: string = "";

  constructor(parameters?: any) {
    toPara(this, parameters);
  }
}

export const toPara = function (thio: any, para: any) {
  for (let x in para) {
    if (typeof (thio as any)[x] !== "undefined") {
      if (typeof para[x] == "boolean" || para[x]) {
        (thio as any)[x] = (para as any)[x];
      }
      // (thio as any)[x] = (para as any)[x];
    }
  }
};
